#include <iostream>

#include <nemesis.Guard.h>
#include <nemesis.functions.h>
#include <nemesis.Logger.h>

#include <nemesis.sdp.Interface.h>

#include <test.SDPCommunicator.h>

using namespace std;
using namespace nemesis;

bool test::SDPCommunicator::canContinue (const sdp::Interface* interface)
   throw (RuntimeException)
{
   Guard guard (this, "test::SDPCommunicator::canContinue");

   if (a_initTime == 0)
      a_initTime = nemesis::functions::milisecond ();

   if (a_messageCounter > 0)
      if (a_messageCounter == a_maxMessage && hasRequestedStop () == false) {
         terminate ();
         return false;
      }

   using namespace nemesis::comm;

   a_messageCounter ++;

   if (interface->haveToDiscard () == true)
      return false;

   a_successCounter ++;

   return true;
}

void test::SDPCommunicator::delay ()
   throw (RuntimeException)
{
  if (a_delay > 0) {
      int random = (a_delay > 10) ? (rand () % (a_delay / 10)): 0;
      int sign = rand () % 2;
   
      if (sign == 0)
         random *= -1;

      const Microsecond init = nemesis::functions::hardwareClock ();

      nemesis::functions::sleep (a_delay + random);

      if (true) {
         Guard guard (this, "test::SDPCommunicator::delay");   
         a_avgDelay += nemesis::functions::hardwareClock () - init;
      }
   }
}

void  test::SDPCommunicator::terminate ()
   throw ()
{
   if (hasRequestedStop () == true)
      return;

   requestStop ();

   const Milisecond serviceTime = nemesis::functions::milisecond () - a_initTime;

   LOGNOTICE (
      const int workload = (serviceTime == 0) ? 0: a_messageCounter * 1000 / serviceTime;   
      string msg (nemesis::functions::asText ("Tiempo de servicio: ", (int) serviceTime));
      msg += nemesis::functions::asText (" ms | Carga: ", workload);
      msg += nemesis::functions::asText (" msg/seg | Mensajes recibidos: ", a_messageCounter);
      msg += nemesis::functions::asText (" | Mensajes tratados: ", a_successCounter);
      Logger::notice (msg, FILE_LOCATION);      
      cout << msg << endl << endl;
      
      msg = "Retardo medio (us) | ";
      msg += a_avgDelay.asString ();
      Logger::notice (msg, FILE_LOCATION);      
      cout << msg << endl << endl;
   );
}

//----------------------------------------------------------------------------------------
// (1) Dos handlers, uno el ServerSocket y otro el ClientSocket que va a cerran =>
// si es asi termina
//----------------------------------------------------------------------------------------
void test::SDPCommunicator::eventOverQuota (const comm::ClientSocket&) 
   throw ()
{
   int counter = 0;

   for (handler_iterator ii = handler_begin (), maxii = handler_end (); ii != maxii; ii ++)
      counter ++;

   LOGNOTICE (
      Logger::notice (nemesis::functions::asText ("Handlers: ", counter), FILE_LOCATION);
   );
      
   if (counter == 2)  // (1)
      terminate ();
}

void test::SDPCommunicator::notifyError ()
   throw (RuntimeException)
{
   Guard guard (this, "test::SDPCommunicator::notifyError");

   if (++ a_errorCounter > 30)
      terminate ();
}

void test::SDPCommunicator::resetError ()
   throw (RuntimeException)
{
   if (a_errorCounter == 0) 
      return;

   Guard guard (this, "test::SDPCommunicator::resetError");
   a_errorCounter = 0;
}
